package org.example.util;

import cn.hutool.json.JSONObject;
import com.aliyun.oss.ServiceException;
import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
import com.itextpdf.html2pdf.resolver.font.DefaultFontProvider;
import com.itextpdf.io.font.PdfEncodings;
import com.itextpdf.io.util.ResourceUtil;
import com.itextpdf.io.util.StreamUtil;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.utils.PdfMerger;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.font.FontProvider;
import com.itextpdf.layout.properties.TextAlignment;
import org.example.domain.PoArriveorderVo;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

public class PdfUtils {

	private static String path = "/";//模板路径
	private static PdfUtils fk;

	private static final String FONT_PATH = "font/simsun.ttc";

	private static final String TEMPLATE_PATH = "template/ftl/test1.ftl";

	private PdfUtils(String templatePath){
		this.path = templatePath;
	}

	public static ConverterProperties  converterProperties() throws IOException {
		FontProvider fp = new FontProvider();
		PdfFont font = PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H");
		fp.addFont(font.getFontProgram(),"UniGB-UCS2-H");

		ConverterProperties p = new ConverterProperties();
		// 注册字体
		fp.addFont(FONT_PATH);
		p.setFontProvider(fp);
		p.setCharset(PdfEncodings.UTF8);
		return p;
	}
	/**
	 *
	 * @param templatePath 模版加载路径
	 * @return
	 */
	public static PdfUtils getInstance(String templatePath){
		if (null == fk) {
			fk = new PdfUtils(templatePath);
		}
		return fk;
	}

	public void change(String feltemp, String jsonStr, String pdffilename){
		FreemarkerUtil fu = FreemarkerUtil.getInstance(FreemarkerUtil.ClassForTemplateLoading, path);
		byte[] u = fu.generatorHtmlByteFromTemplate(feltemp, jsonStr);
		InputStream is = null;
		File out = new File(pdffilename);
		try {
			is = new ByteArrayInputStream(u);
			//PdfFont font = PdfFontFactory.createFont(FontProgramFactory.createFont(FONT_PATH));
			DefaultFontProvider fp = new DefaultFontProvider(true,true,false);
			try (InputStream stream = ResourceUtil.getResourceStream(FONT_PATH)) {
				byte[] fontProgramBytes = StreamUtil.inputStreamToArray(stream);
				fp.addFont(fontProgramBytes, null, null);
			} catch (Exception e) {
				e.printStackTrace();
			}
			//字体路径
			//fp.addFont(font.getFontProgram(), PdfEncodings.IDENTITY_H);
			ConverterProperties p = new ConverterProperties();
			p.setFontProvider(fp);
			p.setCharset(PdfEncodings.UTF8);
			HtmlConverter.convertToPdf(is, new PdfWriter(out) ,p);
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if(is!=null){
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public  void change1(String jsonStr, String pdffilename){
		FreemarkerUtil fu = FreemarkerUtil.getInstance(FreemarkerUtil.ClassForTemplateLoading, path);
		byte[] u = fu.generatorHtmlByteFromTemplate(TEMPLATE_PATH, jsonStr);
		InputStream is = null;
		File out = new File(pdffilename);
		try {
			is = new ByteArrayInputStream(u);
			DefaultFontProvider fp = new DefaultFontProvider(false, false, false);
			try (InputStream stream = ResourceUtil.getResourceStream(FONT_PATH)) {
				byte[] fontProgramBytes = StreamUtil.inputStreamToArray(stream);
				fp.addFont(fontProgramBytes, null, null);
			} catch (Exception e) {
				e.printStackTrace();
			}
			ConverterProperties p = new ConverterProperties();
			// 注册字体
			fp.addFont(FONT_PATH);
			p.setFontProvider(fp);
			p.setCharset(PdfEncodings.UTF8);

			// 创建 PdfDocument 对象并设置页面大小为 A4
			PdfDocument pdfDoc = new PdfDocument(new PdfWriter(out));
			pdfDoc.setDefaultPageSize(PageSize.A4.rotate());

			// 进行 HTML 到 PDF 的转换
			HtmlConverter.convertToPdf(is, pdfDoc, p);

			// 关闭 PdfDocument
			pdfDoc.close();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if(is!=null){
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public static ByteArrayOutputStream change2(String jsonStr, boolean rotate){
		FreemarkerUtil fu = FreemarkerUtil.getInstance(FreemarkerUtil.ClassForTemplateLoading, path);
		byte[] u = fu.generatorHtmlByteFromTemplate(TEMPLATE_PATH, jsonStr);
		InputStream is = null;
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		try {
			is = new ByteArrayInputStream(u);
			ConverterProperties properties = converterProperties();

			// 创建 PdfDocument 对象并设置页面大小为 A4
			PdfDocument pdfDoc = new PdfDocument(new PdfWriter(out));
			if (rotate){
				pdfDoc.setDefaultPageSize(PageSize.A4.rotate());
			}else {
				pdfDoc.setDefaultPageSize(PageSize.A4);
			}

			// 进行 HTML 到 PDF 的转换
			HtmlConverter.convertToPdf(is, pdfDoc, properties);

			// 关闭 PdfDocument
			pdfDoc.close();
			return out;
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if(is!=null){
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return out;
	}

	public static void change1111(HttpServletResponse response, String jsonStr){
		String fileName = LocalDateTime.now().toString() + ".pdf";
		setContentType(response, fileName, FileType.PDF);
		FreemarkerUtil fu = FreemarkerUtil.getInstance(FreemarkerUtil.ClassForTemplateLoading, path);
		byte[] u = fu.generatorHtmlByteFromTemplate(TEMPLATE_PATH, jsonStr);
		InputStream is = null;
		try {
			is = new ByteArrayInputStream(u);
			FontProvider fp = new FontProvider();
			PdfFont font = PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H");
			fp.addFont(font.getFontProgram(),"UniGB-UCS2-H");

			ConverterProperties p = new ConverterProperties();
			// 注册字体
			fp.addFont(FONT_PATH);
			p.setFontProvider(fp);
			p.setCharset(PdfEncodings.UTF8);

			// 创建 PdfDocument 对象并设置页面大小为 A4
			PdfDocument pdfDoc = new PdfDocument(new PdfWriter(response.getOutputStream()));
			pdfDoc.setDefaultPageSize(PageSize.A4.rotate());
			// 进行 HTML 到 PDF 的转换
			HtmlConverter.convertToPdf(is, pdfDoc, p);
			// 关闭 PdfDocument
			pdfDoc.close();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if(is!=null){
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public static void setContentType(HttpServletResponse response, String fileName, FileType fileType) {
		try {
			// 设置响应内容的编码格式为UTF-8
			response.setCharacterEncoding("UTF-8");
			// 根据文件类型设置响应的内容类型
			response.setContentType(fileType.getDesc());
			// 设置响应头，指定文件下载时的文件名和文件类型
			response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8") + fileType.getType());
		} catch (UnsupportedEncodingException e) {
			// 当文件名编码失败时，抛出自定义异常
			throw new ServiceException("设置ContentType失败: " + e.getMessage());
		}
	}

	public static void mergePdfsWithCustomization(List<JSONObject> list, String destinationPath) {
		try (PdfWriter writer = new PdfWriter(destinationPath);
			 PdfDocument destinationPdf = new PdfDocument(writer)) {

			PdfMerger merger = new PdfMerger(destinationPdf);

			for (JSONObject object : list) {
				byte[] bytes = object.getBytes("byte");
				Boolean rotate = object.getBool("rotate", false);
				try (PdfReader reader = new PdfReader(new ByteArrayInputStream(bytes));
					 PdfDocument sourcePdf = new PdfDocument(reader)) {
					if(rotate){
						sourcePdf.setDefaultPageSize(PageSize.A4);
					} else {
						sourcePdf.setDefaultPageSize(PageSize.A4.rotate());
					}


					// 合并前获取源 PDF 的页数
					int pageCount = sourcePdf.getNumberOfPages();

					// 合并当前 PDF 的所有页面
					merger.merge(sourcePdf, 1, pageCount);

					// 为合并后的页面添加自定义内容（如页码）
					for (int i = 0; i < pageCount; i++) {
						int destinationPageNumber = destinationPdf.getNumberOfPages() - pageCount + i + 1;
						PdfPage page = destinationPdf.getPage(destinationPageNumber);

						// 在这里添加自定义内容（如页码、页眉页脚等）
						addPageNumber(destinationPdf, page, destinationPageNumber);
					}
				}
			}

			merger.close();

		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void mergePdfsWithCustomization1111(List<JSONObject> list, String destinationPath) {
		try (PdfWriter writer = new PdfWriter(destinationPath);
			 PdfDocument destinationPdf = new PdfDocument(writer)) {

			PdfMerger merger = new PdfMerger(destinationPdf);

			for (JSONObject object : list) {
				byte[] bytes = object.getBytes("byte");
				Boolean rotate = object.getBool("rotate", false);
				try (PdfReader reader = new PdfReader(new ByteArrayInputStream(bytes));
					 PdfDocument sourcePdf = new PdfDocument(reader)) {
					if(rotate){
						sourcePdf.setDefaultPageSize(PageSize.A4);
					} else {
						sourcePdf.setDefaultPageSize(PageSize.A4.rotate());
					}


					// 合并前获取源 PDF 的页数
					int pageCount = sourcePdf.getNumberOfPages();

					// 合并当前 PDF 的所有页面
					merger.merge(sourcePdf, 1, pageCount);

					// 为合并后的页面添加自定义内容（如页码）
					for (int i = 0; i < pageCount; i++) {
						int destinationPageNumber = destinationPdf.getNumberOfPages() - pageCount + i + 1;
						PdfPage page = destinationPdf.getPage(destinationPageNumber);

						// 在这里添加自定义内容（如页码、页眉页脚等）
						addPageNumber(destinationPdf, page, destinationPageNumber);
					}
				}
			}

			merger.close();

		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void addPageNumber(PdfDocument pdf, PdfPage page, int pageNumber) {
		// 获取页面尺寸
		Rectangle pageSize = page.getPageSize();

		// 创建 Canvas 并添加页码
		Canvas canvas = new Canvas(page, pageSize);
		canvas.setFontSize(10);
		canvas.showTextAligned("Page " + pageNumber,
				pageSize.getWidth() / 2,
				pageSize.getBottom() + 20,
				TextAlignment.CENTER);
		canvas.close();
	}

	public void testMergePdf(){
		List<PoArriveorderVo> poArriveorderVoList = new ArrayList<>();
		// 创建第一个 PoArriveorderVo 对象
		PoArriveorderVo vo1 = new PoArriveorderVo();
		vo1.setId("ZSYS15052025040300001");
		vo1.setWeighingNo(" GB3WN4250331151437MR");
		vo1.setSupplierName("呼伦⻉尔市华亿物资销售有限公司");
		vo1.setPackageBuckleHeavy(new BigDecimal("500.00"));
		vo1.setSrcOrderNo("NC001");
		vo1.setMaterialCode("M001");
		vo1.setMaterialName("钢材");
		vo1.setMaterialInfo("xxxx aaaa");
		vo1.setInventNum(new BigDecimal("100"));
		vo1.setLength(new BigDecimal("2.0"));
		vo1.setWidth(new BigDecimal("1.0"));
		vo1.setHeight(new BigDecimal("0.5"));
		vo1.setConversionStandard(new BigDecimal("1.0"));
		vo1.setArriveNum(new BigDecimal("200.00"));
		vo1.setTheoreticalAcceptanceWeight(new BigDecimal("480.00"));
		vo1.setOrgName("收货公司A");
		vo1.setPkOrgV("C001");
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		vo1.setUpdateDate(null);
		vo1.setVbillcode("V001");
		vo1.setDmakedate(null);
		poArriveorderVoList.add(vo1);

		// 创建第二个 PoArriveorderVo 对象
		PoArriveorderVo vo2 = new PoArriveorderVo();
		vo2.setId("ZSYS15052025040300001");
		vo2.setWeighingNo("ZSYS150520250403009955");
		vo2.setSupplierName("呼伦⻉尔市华亿物资销售有限公司");
		vo2.setPackageBuckleHeavy(new BigDecimal("600.00"));
		vo2.setSrcOrderNo("NC002");
		vo2.setMaterialCode("M002");
		vo2.setMaterialName("木材");
		vo2.setInventNum(new BigDecimal("200"));
		vo2.setLength(new BigDecimal("3.0"));
		vo2.setWidth(new BigDecimal("1.5"));
		vo2.setHeight(new BigDecimal("0.8"));
		vo2.setConversionStandard(new BigDecimal("1.2"));
		vo2.setArriveNum(new BigDecimal("300.00"));
		vo2.setTheoreticalAcceptanceWeight(new BigDecimal("598.24"));
		vo2.setOrgName("收货公司B");
		vo2.setPkOrgV("C002");
		vo2.setUpdateDate(new Date());
		vo2.setVbillcode("V002");
		vo2.setDmakedate(new Date());
		poArriveorderVoList.add(vo2);
		String theoreticalTotal = poArriveorderVoList.stream().map(PoArriveorderVo::getTheoreticalAcceptanceWeight).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add).toPlainString();
		JSONObject jsonObject = new JSONObject();
		jsonObject.set("poArriveorderVoList", poArriveorderVoList);
		jsonObject.set("theoreticalTotal",  null);
		String splitWeightTotal = "987.56";
		jsonObject.set("splitWeightTotal",  null);
		//PdfUtils.getInstance("/").change1( jsonObject.toString() , "test2.pdf");

		ByteArrayOutputStream outputStream1 = change2(jsonObject.toString(), false);
		ByteArrayOutputStream outputStream2 = change2(jsonObject.toString(), true);
		//List<InputStream> byteArrayInputStreams = Arrays.asList(new ByteArrayInputStream(outputStream1.toByteArray()), new ByteArrayInputStream(outputStream2.toByteArray()));
		List<JSONObject> list = new ArrayList<>();
		JSONObject object1 = new JSONObject();
		object1.set("byte", outputStream1.toByteArray());
		object1.set("rotate", false);

		JSONObject object2 = new JSONObject();
		object2.set("byte", outputStream2.toByteArray());
		object2.set("rotate", true);
		list.add(object1);
		list.add(object2);
		mergePdfsWithCustomization(list, "test3.pdf");
	}

}